package org.convallaria.system.biz.util;

import lombok.extern.slf4j.Slf4j;
import org.convallaria.system.biz.service.auth.AuthService;
import org.convallaria.system.biz.service.PerformanceMonitorService;
import org.convallaria.system.biz.service.CacheOptimizationService;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 性能测试工具类
 * 
 * @author convallaria
 * @since 1.0.0
 */
@Slf4j
@Component
public class PerformanceTestUtils {

    private final ExecutorService executorService = Executors.newFixedThreadPool(10);

    /**
     * 执行并发登录测试
     * 
     * @param authService 认证服务
     * @param threadCount 线程数
     * @param requestCount 每个线程的请求数
     * @return 测试结果
     */
    public LoadTestResult performConcurrentLoginTest(AuthService authService, 
                                                   int threadCount, int requestCount) {
        log.info("开始并发登录测试: {} 线程, 每线程 {} 请求", threadCount, requestCount);
        
        List<CompletableFuture<ThreadTestResult>> futures = new ArrayList<>();
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            CompletableFuture<ThreadTestResult> future = CompletableFuture.supplyAsync(() -> {
                return performThreadLoginTest(authService, threadId, requestCount);
            }, executorService);
            futures.add(future);
        }
        
        // 等待所有线程完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
            futures.toArray(new CompletableFuture[0])
        );
        
        try {
            allFutures.get(60, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("并发测试超时", e);
        }
        
        long endTime = System.currentTimeMillis();
        long totalDuration = endTime - startTime;
        
        // 收集结果
        List<ThreadTestResult> threadResults = new ArrayList<>();
        for (CompletableFuture<ThreadTestResult> future : futures) {
            try {
                threadResults.add(future.get());
            } catch (Exception e) {
                log.error("获取线程测试结果失败", e);
            }
        }
        
        return calculateLoadTestResult(threadResults, totalDuration);
    }

    /**
     * 执行缓存性能测试
     * 
     * @param cacheOptimizationService 缓存优化服务
     * @return 测试结果
     */
    public CacheTestResult performCacheTest(CacheOptimizationService cacheOptimizationService) {
        log.info("开始缓存性能测试");
        
        long startTime = System.currentTimeMillis();
        
        // 预热缓存
        cacheOptimizationService.warmupCache();
        
        // 获取缓存统计
        CacheOptimizationService.CacheStatistics stats = cacheOptimizationService.getCacheStatistics();
        
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        return new CacheTestResult(
            stats.getTotalKeys(),
            stats.getHitRate(),
            stats.getMemoryUsage(),
            duration,
            LocalDateTime.now()
        );
    }

    /**
     * 执行性能监控测试
     * 
     * @param performanceMonitorService 性能监控服务
     * @return 测试结果
     */
    public PerformanceTestResult performPerformanceTest(PerformanceMonitorService performanceMonitorService) {
        log.info("开始性能监控测试");
        
        long startTime = System.currentTimeMillis();
        
        // 模拟一些操作
        for (int i = 0; i < 100; i++) {
            performanceMonitorService.recordApiPerformance("test.method", 50 + i, true);
            performanceMonitorService.recordDatabasePerformance("SELECT * FROM test", 100 + i, true);
            performanceMonitorService.recordCachePerformance("GET", "test:key:" + i, 10 + i, true);
        }
        
        // 获取性能统计
        PerformanceMonitorService.PerformanceStatistics stats = 
            performanceMonitorService.getPerformanceStatistics(1);
        
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        return new PerformanceTestResult(
            stats.getTotalRequests(),
            stats.getSuccessRate(),
            stats.getAverageResponseTime(),
            duration,
            LocalDateTime.now()
        );
    }

    /**
     * 执行线程登录测试
     */
    private ThreadTestResult performThreadLoginTest(AuthService authService, int threadId, int requestCount) {
        int successCount = 0;
        int failureCount = 0;
        long totalResponseTime = 0;
        
        for (int i = 0; i < requestCount; i++) {
            long requestStart = System.currentTimeMillis();
            
            try {
                // 模拟登录请求（这里只是测试框架，实际需要真实的登录数据）
                // authService.login(loginDTO);
                successCount++;
            } catch (Exception e) {
                failureCount++;
                log.debug("线程 {} 请求 {} 失败: {}", threadId, i, e.getMessage());
            }
            
            long requestEnd = System.currentTimeMillis();
            totalResponseTime += (requestEnd - requestStart);
        }
        
        return new ThreadTestResult(
            threadId, successCount, failureCount, 
            totalResponseTime / requestCount, LocalDateTime.now()
        );
    }

    /**
     * 计算负载测试结果
     */
    private LoadTestResult calculateLoadTestResult(List<ThreadTestResult> threadResults, long totalDuration) {
        int totalSuccess = threadResults.stream().mapToInt(ThreadTestResult::getSuccessCount).sum();
        int totalFailure = threadResults.stream().mapToInt(ThreadTestResult::getFailureCount).sum();
        double averageResponseTime = threadResults.stream()
            .mapToDouble(ThreadTestResult::getAverageResponseTime)
            .average()
            .orElse(0.0);
        
        return new LoadTestResult(
            totalSuccess + totalFailure,
            totalSuccess,
            totalFailure,
            averageResponseTime,
            totalDuration,
            LocalDateTime.now()
        );
    }

    /**
     * 线程测试结果
     */
    public static class ThreadTestResult {
        private final int threadId;
        private final int successCount;
        private final int failureCount;
        private final double averageResponseTime;
        private final LocalDateTime timestamp;

        public ThreadTestResult(int threadId, int successCount, int failureCount, 
                              double averageResponseTime, LocalDateTime timestamp) {
            this.threadId = threadId;
            this.successCount = successCount;
            this.failureCount = failureCount;
            this.averageResponseTime = averageResponseTime;
            this.timestamp = timestamp;
        }

        // Getters
        public int getThreadId() { return threadId; }
        public int getSuccessCount() { return successCount; }
        public int getFailureCount() { return failureCount; }
        public double getAverageResponseTime() { return averageResponseTime; }
        public LocalDateTime getTimestamp() { return timestamp; }
    }

    /**
     * 负载测试结果
     */
    public static class LoadTestResult {
        private final int totalRequests;
        private final int successCount;
        private final int failureCount;
        private final double averageResponseTime;
        private final long totalDuration;
        private final LocalDateTime timestamp;

        public LoadTestResult(int totalRequests, int successCount, int failureCount,
                            double averageResponseTime, long totalDuration, LocalDateTime timestamp) {
            this.totalRequests = totalRequests;
            this.successCount = successCount;
            this.failureCount = failureCount;
            this.averageResponseTime = averageResponseTime;
            this.totalDuration = totalDuration;
            this.timestamp = timestamp;
        }

        // Getters
        public int getTotalRequests() { return totalRequests; }
        public int getSuccessCount() { return successCount; }
        public int getFailureCount() { return failureCount; }
        public double getAverageResponseTime() { return averageResponseTime; }
        public long getTotalDuration() { return totalDuration; }
        public LocalDateTime getTimestamp() { return timestamp; }
        
        public double getSuccessRate() {
            return totalRequests > 0 ? (double) successCount / totalRequests : 0.0;
        }
        
        public double getThroughput() {
            return totalDuration > 0 ? (double) totalRequests / totalDuration * 1000 : 0.0;
        }
    }

    /**
     * 缓存测试结果
     */
    public static class CacheTestResult {
        private final long totalKeys;
        private final double hitRate;
        private final long memoryUsage;
        private final long duration;
        private final LocalDateTime timestamp;

        public CacheTestResult(long totalKeys, double hitRate, long memoryUsage, 
                             long duration, LocalDateTime timestamp) {
            this.totalKeys = totalKeys;
            this.hitRate = hitRate;
            this.memoryUsage = memoryUsage;
            this.duration = duration;
            this.timestamp = timestamp;
        }

        // Getters
        public long getTotalKeys() { return totalKeys; }
        public double getHitRate() { return hitRate; }
        public long getMemoryUsage() { return memoryUsage; }
        public long getDuration() { return duration; }
        public LocalDateTime getTimestamp() { return timestamp; }
    }

    /**
     * 性能测试结果
     */
    public static class PerformanceTestResult {
        private final long totalRequests;
        private final double successRate;
        private final double averageResponseTime;
        private final long duration;
        private final LocalDateTime timestamp;

        public PerformanceTestResult(long totalRequests, double successRate, 
                                   double averageResponseTime, long duration, LocalDateTime timestamp) {
            this.totalRequests = totalRequests;
            this.successRate = successRate;
            this.averageResponseTime = averageResponseTime;
            this.duration = duration;
            this.timestamp = timestamp;
        }

        // Getters
        public long getTotalRequests() { return totalRequests; }
        public double getSuccessRate() { return successRate; }
        public double getAverageResponseTime() { return averageResponseTime; }
        public long getDuration() { return duration; }
        public LocalDateTime getTimestamp() { return timestamp; }
    }
}
